/*=====================================================================

  File:      FetchStreamPull.cs
  Summary:   SQL Remote Blob Storage sample application - FetchStreamPull.
             Sample application used to fetch blob data from the 
             sample application's tables. Uses the pull streaming calls.
  Date:	     July 21st, 2008

---------------------------------------------------------------------

  This file is part of the Microsoft SQL Server Code Samples.
  Copyright (C) Microsoft Corporation.  All rights reserved.

This source code is intended only as a supplement to Microsoft
Development Tools and/or on-line documentation.  See these other
materials for detailed information regarding Microsoft code samples.

THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.

======================================================= */

using System;
using System.Data;
using System.Data.SqlClient;
using System.Globalization;
using System.Text;

using Microsoft.Data.SqlRemoteBlobs;

namespace Microsoft.Samples.RemoteBlobStorage
{
    /// <summary>
    /// Sample Remote Blob Storage Application.
    /// </summary>
    public
    sealed
    class FetchStreamPull
    {
        private FetchStreamPull() { }

        public
        static
        void RunFetchStreamPull(string connectionString)
        {
            Console.WriteLine("Running the FetchStreamPull Sample");

            // Reads all blob data from the application's tables.
            //
            using (SqlConnection conn = new SqlConnection(connectionString))
            {
                conn.Open();

                // Create a blob context to operate againt RBS.
                //
                SqlRemoteBlobContext blobContext = new SqlRemoteBlobContext(conn);

                // Fetch this blob using the blobId retrieved from running a query against the SearchTags field.
                // No specific collection information is required for Fetch as this information is coded into
                // the BlobId.
                //
                // Using the rbs_fn_get_blob_reference function converts the BlobId into a blob reference, which 
                // contains store specific information regarding the location of the blob. This is an optional step - 
                // passing the blob id to the SqlRemoteBlobContext.OpenBlob method will still function but will 
                // require an extra internal round trip to the database to do the conversion.
                //
                //                   ** WARNING NON OPTIMAL EXAMPLE ** 
                // For this example we just retrieve the BlobId. This will cause an extra trip to the database
                // when the blob is attempted to be retrieved.
                // See the Fetch Simple example for the optimized case that removes the need for this extra trip.
                //
                string queryBlobEntry = @" 
                                select 
                                    BlobId
                                from 
                                    ApplicationSampleTable 
                                where 
                                    SearchTags LIKE '%Sample%'
                                ";

                DataTable blobIds = new DataTable();
                blobIds.Locale = CultureInfo.InvariantCulture;

                // Run a query, returning all the blob IDs.
                //
                using (SqlCommand cmd = new SqlCommand(queryBlobEntry, conn))
                {
                    // Fill the blob references and close the command.
                    //
                    using (SqlDataAdapter adapter = new SqlDataAdapter(cmd))
                    {
                        adapter.Fill(blobIds);
                    }
                }

                // Database access will still be required as the BlobId will need to 
                // be converted to a BlobReference internally.
                //
                
                // Cycle through all the returned rows and process each in turn.
                //
                Console.WriteLine("Reading blob data (Stream Pull):");
                foreach (DataRow dr in blobIds.Rows)
                {
                    // Get the BlobId
                    //
                    byte[] blobId = (byte[])dr[0];

                    // Get a stream with blob data. Reuse the blobContext created initially.
                    //
                    using (SqlRemoteBlob blob = blobContext.OpenBlob(blobId))
                    {
                        // The SqlRemoteBlob object inherits from System.IO.Stream and can be used as such.
                        // Here we 'pull' the contents of the returned blob stream into a buffer which is 
                        // then output to the console.
                        //
                        byte[] readdata = new byte[256];
                        blob.Read(readdata, 0, readdata.Length);
                        Console.WriteLine(Encoding.Unicode.GetString(readdata));
                    }
                }
            }

            // Success
            //
        }
    }
}
